<template>
  <div
      ref="containerRef"
      class="map-container"
      style="width: 100%; height: 100%"
      v-loading="loading"
      @click="handleClick"
  >
    <!-- Three.js 场景会在这个容器中渲染 -->
    <div class="tooltip" ref="tooltipRef"></div>
  </div>
</template>

<script setup>
import axios from "axios";
import {ref, onMounted, onBeforeUnmount, watch} from "vue";
import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {geoMercator} from "d3-geo";
import LightSweepMaterial from "../../utils/lightSweepMaterial.js";
import {RGBELoader} from "three-stdlib";
import {TextGeometry} from "three/examples/jsm/geometries/TextGeometry.js";
import {FontLoader} from "three/examples/jsm/loaders/FontLoader.js";

import {
  CSS2DObject,
  CSS2DRenderer,
} from "three/examples/jsm/renderers/CSS2DRenderer.js";
import {mergeGeometries} from "three/examples/jsm/utils/BufferGeometryUtils.js";

// 全局变量
let jsondata = null;
let camera = null;
let scene = null;
let renderer = null;
let controls = null;
let map = null;
let midMap = null;
let baseMap = null;
let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();
let lastPick = null;
let lightMesh = null;
let lightMaterial = null;
let gridHelper = null;
let labelRenderer = new CSS2DRenderer();
let target = null; // 目标省份
const ringWidth = 0.1;
const T = Math.PI / 2;
const projectionFn = geoMercator()
    .center([104.0, 37.5])
    .scale(80)
    .translate([0, 0]);

// setup function variables
const loading = ref(true);
const containerRef = ref(null);
const tooltipRef = ref(null);
const mapInitPosition = {x: 0, y: 6, z: 0};
const mapDepth = 6;
const isAnimating = ref(true);

let dataList = [
  {
    "code": "110000",
    "gCount": 12345,
    "aCount": 6789
  },
  // 其他地区...
]
const props = defineProps({
  provinceAdcode: {
    type: Number,
    default: 0,
  },
});

const emit = defineEmits(["selProvince", "getMapData"]);
const initializeThree = () => {
  const width = containerRef.value.clientWidth;
  const height = 500;

  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color("#ffffff");

  // 创建相机
  camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 1000);
  camera.position.set(0, -20, 80);

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(width, height);

  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 环境光
  scene.add(ambientLight);

  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 方向光
  directionalLight.position.set(1, 1, 1).normalize();
  scene.add(directionalLight);

  // 将渲染器的DOM元素（canvas）添加到容器中
  containerRef.value.appendChild(renderer.domElement);

  // 添加控制器
  controls = new OrbitControls(camera, renderer.domElement);

  // 使用 RGBELoader 加载 HDR 环境贴图
  const loader = new RGBELoader();
  loader.load("http://47.105.210.118:10005/json/umhlanga_sunrise_1k.hdr", function (texture) {
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.environment = texture;
  });

  // 添加扩散圈
  const geometry = new THREE.PlaneGeometry(290, 290);
  lightMaterial = new LightSweepMaterial();
  lightMesh = new THREE.Mesh(geometry, lightMaterial);
  scene.add(lightMesh);

  // 添加网格
  gridHelper = new THREE.GridHelper(2000, 100, "#bbb", "#bbb");
  gridHelper.rotation.x = -Math.PI / 2;
  gridHelper.position.set(0, -0.01, 0);
  scene.add(gridHelper);

  // 加载地图数据
  loadMapData();
  // fetchMapData(110000);

  // 初始化 labelRenderer
  initLabelRenderer();

  // 开始渲染循环
  animate();
};

// 初始化 labelRenderer
const initLabelRenderer = () => {
  const width = containerRef.value.clientWidth;
  const height = 500;
  labelRenderer.domElement.style.position = "absolute";
  labelRenderer.domElement.style.top = "0px";
  labelRenderer.domElement.style.pointerEvents = "none";
  labelRenderer.setSize(width, height);
  containerRef.value.appendChild(labelRenderer.domElement);
};
// 加载地图数据的逻辑
const loadMapData = () => {
  const loader = new THREE.FileLoader();
  loader.load("/json/ChinaMap.json", (data) => {
    jsondata = JSON.parse(data);
    createMap(jsondata);
    createMidMap(jsondata);
    createBaseMap(jsondata);
  });
};
// 在线加载地图数据
const fetchMapData = async (code) => {
  try {
    const response = await axios.get(
        `https://geo.datav.aliyun.com/areas_v3/bound/${code}_full.json`
    );
    jsondata = response.data;
    createMap(jsondata);
    createMidMap(jsondata);
    createBaseMap(jsondata);
  } catch (error) {
    console.error("Error fetching map data:", error);
  }
};

// 创建地图
const createMap = (data) => {
  map = new THREE.Object3D();
  const projection = getProjection();
  // 计算 data.features 中的最大 value 值
  var arr = data.features.map((elem) => elem.properties.subFeatureIndex);
  let filteredNumbers = arr.filter(
      (value) => typeof value === "number" && !isNaN(value)
  );
  const calcShowHeight = (count) => {
    // 根据 count 计算柱形图的高度
    return count * 0.001; // 示例计算方法，可以根据实际需求调整
  };
  const maxFeatureValue = Math.max(...filteredNumbers);
  data.features.forEach((elem) => {
    // Map rendering logic
    const province = new THREE.Object3D();
    const {coordinates} = elem.geometry;
    coordinates.forEach((multiPolygon) => {
      multiPolygon.forEach((polygon) => {
        const shape = new THREE.Shape();
        const lineGeometry = new THREE.BufferGeometry();
        const pointsArray = [];
        for (let i = 0; i < polygon.length; i++) {
          const [x, y] = projection(polygon[i]);
          if (i === 0) {
            shape.moveTo(x, -y);
          } else {
            shape.lineTo(x, -y);
          }
          pointsArray.push(new THREE.Vector3(x, -y, mapDepth / 24));
        }
        lineGeometry.setFromPoints(pointsArray);

        const extrudeSettings = {
          depth: mapDepth / 24,
          bevelEnabled: false,
        };
        const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

        // 动态计算 transmission 和 roughness 值
        const transmissionValue = Math.sqrt(
            elem.properties.subFeatureIndex / maxFeatureValue
        );
        const roughnessValue = Math.sqrt(
            elem.properties.subFeatureIndex / maxFeatureValue
        );
        // 配置 MeshPhysicalMaterial 参数
        const config = {
          color: "#9cb8e4",
          clearcoat: 0.5,
          reflectivity: 0.35,
          ior: 1.3,
          transmission: transmissionValue, // 计算后的透明度
          roughness: roughnessValue, // 计算后的粗糙度
          thickness: 0.1, // 固定厚度
        };

        // 使用 MeshPhysicalMaterial 创建材质
        const material = new THREE.MeshPhysicalMaterial(config);

        const mesh = new THREE.Mesh(geometry, material);
        const lineMaterial = new THREE.LineBasicMaterial({
          color: "white",
        });
        const line = new THREE.Line(lineGeometry, lineMaterial);
        province.properties = elem.properties;
        province.add(mesh);
        province.add(line);
      });
    });

    // **城市名称**
    // 获取城市名称的位置（使用质心作为位置）
    const cityName = elem.properties.name;
    const centroid = elem.properties.centroid ||
        elem.properties.center || [0, 0];
    if (centroid) {
      const [x, y] = projectionFn(centroid);
      let label = createLabel(cityName, centroid, 0.01);
      map.add(label);

      // 假设 data 是一个包含 adcode, gCount, aCount 的数组
      const curArea = dataList.find(v => v.code == elem.properties.adcode);
      const gCount = curArea ? curArea.gCount : 0;
      const aCount = curArea ? curArea.aCount : 0;

      // 创建柱形图
      const boxR = 0.2; // 柱形图的半径
      const gapWidth = 0.1; // 柱形图之间的间距
      const textOffset = 0.1; // 文本的偏移量

      // 创建采集柱形图
      const geometry_g = new THREE.CylinderGeometry(boxR, boxR, calcShowHeight(gCount), 100);
      const material_g = new THREE.MeshPhongMaterial({
        color: '#0DEAF8',
        transparent: true,
        opacity: 0.8,
      });
      const cylinder1 = new THREE.Mesh(geometry_g, material_g);
      cylinder1.position.set(x - gapWidth, -y, calcShowHeight(gCount) / 2 + mapDepth / 24);
      cylinder1.rotateX(Math.PI / 2);
      province.add(cylinder1);

      // 创建预警柱形图
      const geometry_w = new THREE.CylinderGeometry(boxR, boxR, calcShowHeight(aCount), 100);
      const material_w = new THREE.MeshPhongMaterial({
        color: '#FFBC00',
        transparent: true,
        opacity: 0.8
      });
      const cylinder2 = new THREE.Mesh(geometry_w, material_w);
      cylinder2.position.set(x + gapWidth, -y, calcShowHeight(aCount) / 2 + mapDepth / 24);
      cylinder2.rotateX(Math.PI / 2);
      province.add(cylinder2);

      if (gCount > 0) {
        // 创建采集数量文本
        const gText = createText(gCount.toString(), {
          x: x - gapWidth - boxR / 2 * (gCount.toString()).length,
          y: -y,
          z: calcShowHeight(gCount) + mapDepth / 24 + textOffset
        }, province);
        province.add(gText);

        //创建预警数量文本
        const aText = createText(aCount.toString(), {
          x: x + gapWidth - boxR / 2 * (aCount.toString()).length,
          y: -y,
          z: calcShowHeight(aCount) + mapDepth / 24 + textOffset
        }, province);
        province.add(aText);
      }

    }
    map.add(province);

  });

  map.position.set(
      mapInitPosition.x,
      mapInitPosition.y,
      mapInitPosition.z + 7.5
  );
  scene.add(map);
  loading.value = false;
  changeProvince(props.provinceAdcode);
};

const createText = (text, position, province, fontSize = 1) => {
  // 加载字体
  const loader = new FontLoader();
  loader.load('/MFTianLiNoncommercial_Regular.json', (font) => {
    const shapes = font.generateShapes(text, fontSize);

    const geometry = new THREE.ShapeGeometry(shapes);

    const material = new THREE.MeshBasicMaterial({
      color: "#f10d0d", // 文本颜色
      side: THREE.DoubleSide // 双面显示，确保从任何角度都能看到文本
    });

    const textMesh = new THREE.Mesh(geometry, material);
    console.log("=>(chinaMap.vue:333) textMesh", textMesh);
    textMesh.position.set(position.x, position.y, position.z);
    textMesh.rotateX(Math.PI / 2); // 旋转以适应地图平面


    // 确保 province 是有效的
    if (province instanceof THREE.Object3D) {
      province.add(textMesh);
    } else {
      console.error('Invalid province object:', province);
    }
  });
};

const createMidMap = (data) => {
  // 创建中间地图
  midMap = new THREE.Object3D();
  const projection = getProjection();
  data.features.forEach((elem) => {
    const province = new THREE.Object3D();
    const {coordinates} = elem.geometry;
    coordinates.forEach((multiPolygon) => {
      multiPolygon.forEach((polygon) => {
        const shape = new THREE.Shape();
        const pointsArray = [];
        for (let i = 0; i < polygon.length; i++) {
          const [x, y] = projection(polygon[i]);
          if (i === 0) {
            shape.moveTo(x, -y);
          } else {
            shape.lineTo(x, -y);
          }
          pointsArray.push(new THREE.Vector3(x, -y, mapDepth));
        }
        // lineGeometry.setFromPoints(pointsArray);

        const extrudeSettings = {
          depth: mapDepth,
          bevelEnabled: false,
        };
        const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

        // 配置 MeshPhysicalMaterial 参数
        const config = {
          color: "#d2ebff",
          transmission: 1, // 模拟玻璃效果
          thickness: 0.3, // 调整厚度
          roughness: 0.6, // 控制表面粗糙度
          ior: 1, // 设置折射率
          clearcoat: 0.5, // 添加清漆效果
          clearcoatRoughness: 0.1, // 清漆粗糙度
          reflectivity: 0.35, // 反射率
        };

        // 使用 MeshPhysicalMaterial 创建材质
        const material = new THREE.MeshPhysicalMaterial(config);
        const mesh = new THREE.Mesh(geometry, material);
        province.properties = elem.properties;
        province.add(mesh);
      });
    });
    midMap.add(province);
  });
  midMap.position.set(
      mapInitPosition.x,
      mapInitPosition.y,
      mapInitPosition.z + 1.5
  );
  scene.add(midMap); // 将地图添加到场景
};

const createBaseMap = (data) => {
  baseMap = new THREE.Object3D(); // 创建地图对象
  const projection = getProjection();
  const geometries = []; // 用于存储每个省份的几何体

  data.features.forEach((elem) => {
    const {coordinates} = elem.geometry;
    coordinates.forEach((multiPolygon) => {
      multiPolygon.forEach((polygon) => {
        const shape = new THREE.Shape();
        for (let i = 0; i < polygon.length; i++) {
          const [x, y] = projection(polygon[i]);
          if (i === 0) {
            shape.moveTo(x, -y); // 移动到轮廓的起点
          } else {
            shape.lineTo(x, -y); // 画轮廓线
          }
        }
        const extrudeSettings = {
          depth: mapDepth / 4,
          bevelEnabled: false,
        };

        // 使用当前省份的轮廓生成 ExtrudeGeometry
        const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
        geometry.translate(0, 0, 0); // 确保几何体位置正确

        geometries.push(geometry); // 将每个省份的几何体加入数组
      });
    });
  });

  // 使用 BufferGeometryUtils 合并几何体
  const mergedGeometry = mergeGeometries(geometries);

  // 创建材质
  const textureLoader = new THREE.TextureLoader();
  const matcap = textureLoader.load("http://47.105.210.118:10005/json/C7C7D7_4C4E5A_818393_6C6C74-512px.png");
  const material = new THREE.MeshMatcapMaterial({matcap});

  // 将合并后的几何体创建为一个 Mesh
  const mergedMesh = new THREE.Mesh(mergedGeometry, material);
  console.log(mergedMesh);

  baseMap.add(mergedMesh); // 将合并后的 Mesh 添加到 baseMap
  baseMap.position.set(mapInitPosition.x, mapInitPosition.y, mapInitPosition.z);
  scene.add(baseMap); // 将地图添加到场景
};

const createLabel = (name, point, depth) => {
  const div = document.createElement("div");
  div.style.color = "#000";
  div.style.fontSize = "12px";
  div.style.textShadow = "1px 1px 2px #047cd6";
  div.textContent = name;
  const label = new CSS2DObject(div);
  label.scale.set(1, 1, 1);
  const [x, y] = projectionFn(point);
  label.position.set(x, -y, depth);
  return label;
};
// 设置投影函数
const getProjection = () => {
  return geoMercator().center([104.0, 37.5]).scale(80).translate([0, 0]);
};

// 动画循环
const animate = () => {
  if (!isAnimating.value) return;
  requestAnimationFrame(animate);
  labelRenderer.render(scene, camera);
  // const elapsedTime = performance.now() / 3000;
  // const stage = (elapsedTime / T) % 2;
  //
  // if (stage < 1) {
  //   lightMaterial.uniforms.innerRadius.value =
  //     1.5 * Math.abs(Math.sin(elapsedTime));
  // } else {
  //   lightMaterial.uniforms.innerRadius.value = 0;
  // }
  //
  // lightMaterial.uniforms.ringWidth.value = ringWidth;

  controls.update();
  renderer.render(scene, camera);
};
const handleClick = (e) => {
  if (!mouse) {
    mouse = new THREE.Vector2();
  }
  mouse.x =
      ((e.clientX - renderer.domElement.getBoundingClientRect().left) /
          renderer.domElement.clientWidth) *
      2 -
      1;
  mouse.y =
      -(
          (e.clientY - renderer.domElement.getBoundingClientRect().top) /
          renderer.domElement.clientHeight
      ) *
      2 +
      1;
  if (map) {
    if (lastPick) {
      lastPick.object.scale.set(1, 1, 1);
      const config = {
        color: "#9cb8e4",
        clearcoat: 0.5,
        reflectivity: 0.35,
        ior: 1.3,
        transmission: 0.5, // 计算后的透明度
        roughness: 0.5, // 计算后的粗糙度
        thickness: 0.1, // 固定厚度
      };

      // 使用 MeshPhysicalMaterial 创建材质
      const material = new THREE.MeshPhysicalMaterial(config);
      lastPick.object.material = material;
    }
    lastPick = null;
    const mouseVector = new THREE.Vector2(mouse.x, mouse.y);

    // 使用点击位置进行射线检测
    raycaster.setFromCamera(mouseVector, camera);
    const intersects = raycaster.intersectObjects(scene.children, true);

    // 查找特定材质的对象
    lastPick = intersects.find(
        (item) =>
            item.object.material &&
            item.object.material.type === "MeshPhysicalMaterial" &&
            item.object.material.thickness == 0.1
    );
    if (
        lastPick &&
        lastPick.object?.parent?.properties?.adcode != props.provinceAdcode
    ) {
      const config = {
        color: "#9cb8e4",
        clearcoat: 0.5,
        reflectivity: 0.35,
        ior: 1.3,
        transmission: 0.5, // 计算后的透明度
        roughness: 0.5, // 计算后的粗糙度
        thickness: 0.1, // 固定厚度
      };

      // 使用 MeshPhysicalMaterial 创建材质
      const material = new THREE.MeshPhysicalMaterial(config);
      target.children[0].material = material;
      target.children[0].scale.set(1, 1, 1);
    }
    if (lastPick && lastPick.object?.parent?.properties?.name) {
      emit("selProvince", lastPick.object?.parent?.properties?.adcode);
      emit("getMapData", lastPick.object?.parent?.properties);
      const config = {
        color: "#ffb47e",
        clearcoat: 0.5,
        reflectivity: 0.35,
        ior: 1.3,
        transmission: 0.5, // 计算后的透明度
        roughness: 0.5, // 计算后的粗糙度
        thickness: 0.1, // 固定厚度
      };

      // 使用 MeshPhysicalMaterial 创建材质
      const material = new THREE.MeshPhysicalMaterial(config);
      lastPick.object.material = material;
      console.log(lastPick);
      lastPick.object.scale.set(1, 1, 3.5);
    }
  }

  controls.update(); // 更新控制器
};
// 窗口调整大小
const onWindowResize = () => {
  const width = containerRef.value.clientWidth;
  const height = containerRef.value.clientHeight;
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
  renderer.setSize(width, height);
};

onMounted(() => {
  isAnimating.value = true;
  labelRenderer = new CSS2DRenderer();
  initializeThree();
  window.addEventListener("resize", () => {
    const width = containerRef.value.clientWidth;
    const height = containerRef.value.clientHeight;
    camera.aspect = width / height;
    //更新摄像机的投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(width, height);
    //设置渲染器的像素比
    renderer.setPixelRatio(window.devicePixelRatio);
  });
  // window.addEventListener("click", handleClick, false);
});
const changeProvince = (adcode) => {
  if (adcode) {
    target = map.children.find((n) => n.properties?.adcode === adcode);
    if (target) {
      // target.visible= true;
      const config = {
        color: "#ffb47e",
        clearcoat: 0.5,
        reflectivity: 0.35,
        ior: 1.3,
        transmission: 0.5, // 计算后的透明度
        roughness: 0.5, // 计算后的粗糙度
        thickness: 0.1, // 固定厚度
      };

      // 使用 MeshPhysicalMaterial 创建材质
      const material = new THREE.MeshPhysicalMaterial(config);
      target.children[0].material = material;
      target.children[0].scale.set(1, 1, 3.5);
    }
  }
};
onBeforeUnmount(() => {
  window.removeEventListener("resize", onWindowResize);
  isAnimating.value = false;
  if (renderer) renderer.dispose();
  if (controls) controls.dispose();
  if (labelRenderer?.domElement?.parentNode) {
    labelRenderer.domElement.parentNode.removeChild(labelRenderer.domElement);
  }
});
// 监听 props.tableData 的变化
// watch(
//     () => props.provinceAdcode,
//     (newVal) => {
//       changeProvince(newVal);
//     }
// );
</script>

<style scoped>
.map-container {
  position: relative;
}
</style>
    